package jp.sinmetal.trainer.action;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.OptimisticLockException;
import javax.servlet.http.HttpServletRequest;

import jp.sinmetal.trainer.entity.Convention;
import jp.sinmetal.trainer.entity.ConventionLog;
import jp.sinmetal.trainer.form.ConventionLogForm;
import jp.sinmetal.trainer.service.ConventionFacadeService;
import jp.sinmetal.trainer.service.ConventionLogService;
import jp.sinmetal.trainer.util.DateUtil;

import org.apache.struts.action.ActionMessage;
import org.apache.struts.util.TokenProcessor;
import org.seasar.framework.beans.util.Beans;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;
import org.seasar.struts.exception.ActionMessagesException;

/**
 * 大会ログアクション
 * @author sin
 *
 */
public class ConventionLogAction extends AbstractAction {

	/**
	 * 対戦パス
	 * @author sin
	 */
	protected final Integer BATTLE_RESULT_PASS = 0;

    /**
     * 大会
     * @author sin
     */
    public ConventionLog conventionLog;

    /**
     * 大会結果マップ
     * @author sin
     */
    public Map<Integer, String> battleResultMap;

    /**
     * 大会ログアクションフォーム
     * @author sin
     */
    @ActionForm
    @Resource
    protected ConventionLogForm conventionLogForm;

    /**
     * HttpRequest
     * @author ishimura
     */
    @Resource
    protected HttpServletRequest request;

    /**
     * 大会ファサードサービス
     * @author sin
     */
    @Resource
    protected ConventionFacadeService conventionFacadeService;
    /**
     * 大会ログサービス
     * @author sin
     */
    @Resource
    protected ConventionLogService conventionLogService;

    /**
     * エントリーポイント
     * 大会ログ情報表示
     * @author sin
     *
     * @return
     */
    @Execute(input = "/convention", urlPattern = "{conventionLogId}")
    public String index() {
    	TokenProcessor.getInstance().saveToken(request);

    	conventionLog = conventionLogService.findById(Integer.parseInt(conventionLogForm.conventionLogId));
    	Beans.copy(conventionLog, conventionLogForm).dateConverter(DATE_FORMAT).execute();
    	battleResultMap = createBattleResultMap(conventionLog);

        return "show.jsp";
    }

    /**
     * 勝利ユーザ登録
     * @author sin
     *
     * @return
     */
    @Execute(input = "{conventionLogId}", redirect = true)
    public String registWinMember() {
    	if (!TokenProcessor.getInstance().isTokenValid(request, true)) {
    		String.format("/convention/%s", conventionLogForm.conventionId);
    	}

    	ConventionLog conventionLog = conventionLogService.findById(Integer.parseInt(conventionLogForm.conventionLogId));
    	if(!isConventionLogMember(conventionLog, memberInfo.memberId) && !isConventionOwner(conventionLog.conventionId)) {
    		ActionMessagesException ex = new ActionMessagesException("It's a dummy!!");
			ex.addMessage("error", new ActionMessage("errors.NotConventionLogMember"));
			throw ex;
    	}

    	ConventionLog entity = buildeConventionLog4BattleResult(conventionLogForm, conventionLog);
    	try {
    		conventionFacadeService.registBattleResult(entity);
    	} catch(OptimisticLockException e) {
    		ActionMessagesException ex = new ActionMessagesException("It's a dummy!!");
			ex.addMessage("error", new ActionMessage("errors.exclusion"));
			throw ex;
    	}

    	return String.format("/convention/%s", conventionLogForm.conventionId);
    }

    /**
     * 対戦者かどうか
     * @author sin
     *
     * @param conventionLog
     * @param memberId
     * @return
     */
    protected boolean isConventionLogMember(ConventionLog conventionLog,  Integer memberId) {
    	return (conventionLog.conventionMember1st.memberId.equals(memberId) || conventionLog.conventionMember2nd.memberId.equals(memberId));
    }

    /**
     * 大会主催者かどうか
     * @author sin
     *
     * @param conventionId
     * @return
     */
    protected boolean isConventionOwner(Integer conventionId) {
    	Convention convention = conventionFacadeService.findConventionById(conventionId);
    	return (convention.memberId.equals(memberInfo.memberId));
    }

    /**
     * 対戦結果Map作成
     * @author sin
     *
     * @param conventionLog
     * @return
     */
    protected Map<Integer, String> createBattleResultMap(ConventionLog conventionLog) {
    	battleResultMap = new LinkedHashMap<Integer, String>();
    	battleResultMap.put(conventionLog.conventionMemberId1st, String.format("%sの勝利", conventionLog.conventionMember1st.member.twitterName));
    	battleResultMap.put(conventionLog.conventionMemberId2nd, String.format("%sの勝利", conventionLog.conventionMember2nd.member.twitterName));
    	battleResultMap.put(BATTLE_RESULT_PASS, "対戦パス");
    	return battleResultMap;
    }

    /**
     * 対戦結果登録用ConventionLog作成
     * @author sin
     *
     * @param form
     * @param conventionLog
     * @return
     */
    protected ConventionLog buildeConventionLog4BattleResult(ConventionLogForm form, ConventionLog conventionLog) {
    	ConventionLog entity = ConventionLog.getInstance(conventionLogForm);
    	if (!form.winConventionMemberId.equals(BATTLE_RESULT_PASS.toString())) {
    		entity.conventionLogState = ConventionLog.STATE_WIN;
    	} else {
    		entity.conventionLogState = ConventionLog.STATE_PASS;
    	}
    	Beans.copy(conventionLog, entity).includes("conventionMemberId1st", "conventionMemberId2nd").execute();
    	entity.updateDate = DateUtil.getNow();
    	return entity;
    }
}